-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[SPIRV][SPIRVPrepareGlobals] Convert llvm.embedded.module from a 0-element array to a 1-element array #166950
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SPIRV][SPIRVPrepareGlobals] Convert llvm.embedded.module from a 0-element array to a 1-element array #166950
Conversation
|
@llvm/pr-subscribers-backend-spir-v Author: Juan Manuel Martinez Caamaño (jmmartinez) ChangesWhen compiling with For AMD flavored SPIRV, we extend the To achieve this, this patch adds a new pass, This is a second attempt at #162082, but cleaner. In the translator something similar is done for every 0-element array since KhronosGroup/SPIRV-LLVM-Translator#2743 . But I don't think we want to do this mapping for all cases. Full diff: https://github.com/llvm/llvm-project/pull/166950.diff 7 Files Affected:
diff --git a/llvm/lib/Target/SPIRV/CMakeLists.txt b/llvm/lib/Target/SPIRV/CMakeLists.txt
index eab7b213756b3..79b76165cd57a 100644
--- a/llvm/lib/Target/SPIRV/CMakeLists.txt
+++ b/llvm/lib/Target/SPIRV/CMakeLists.txt
@@ -41,6 +41,7 @@ add_llvm_target(SPIRVCodeGen
SPIRVPreLegalizerCombiner.cpp
SPIRVPostLegalizer.cpp
SPIRVPrepareFunctions.cpp
+ SPIRVPrepareGlobals.cpp
SPIRVRegisterBankInfo.cpp
SPIRVRegisterInfo.cpp
SPIRVRegularizer.cpp
diff --git a/llvm/lib/Target/SPIRV/SPIRV.h b/llvm/lib/Target/SPIRV/SPIRV.h
index efd49b930aa34..fa85ee781c249 100644
--- a/llvm/lib/Target/SPIRV/SPIRV.h
+++ b/llvm/lib/Target/SPIRV/SPIRV.h
@@ -31,6 +31,7 @@ FunctionPass *createSPIRVPreLegalizerCombiner();
FunctionPass *createSPIRVPreLegalizerPass();
FunctionPass *createSPIRVPostLegalizerPass();
ModulePass *createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM);
+ModulePass *createSPIRVPrepareGlobalsPass();
MachineFunctionPass *createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM);
InstructionSelector *
createSPIRVInstructionSelector(const SPIRVTargetMachine &TM,
@@ -51,6 +52,7 @@ void initializeSPIRVLegalizePointerCastPass(PassRegistry &);
void initializeSPIRVRegularizerPass(PassRegistry &);
void initializeSPIRVMergeRegionExitTargetsPass(PassRegistry &);
void initializeSPIRVPrepareFunctionsPass(PassRegistry &);
+void initializeSPIRVPrepareGlobalsPass(PassRegistry &);
void initializeSPIRVStripConvergentIntrinsicsPass(PassRegistry &);
void initializeSPIRVLegalizeImplicitBindingPass(PassRegistry &);
} // namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp
new file mode 100644
index 0000000000000..c44c53129f1e0
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp
@@ -0,0 +1,68 @@
+//===-- SPIRVPrepareGlobals.cpp - Prepare IR SPIRV globals ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// The pass transforms IR globals that cannot be trivially mapped to SPIRV
+// into something that is trival to lower.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRV.h"
+
+#include "llvm/IR/Module.h"
+
+using namespace llvm;
+
+namespace {
+
+struct SPIRVPrepareGlobals : public ModulePass {
+ static char ID;
+ SPIRVPrepareGlobals() : ModulePass(ID) {}
+
+ StringRef getPassName() const override {
+ return "SPIRV prepare global variables";
+ }
+
+ bool runOnModule(Module &M) override;
+};
+
+bool tryExtendLLVMBitcodeMarker(GlobalVariable &Bitcode) {
+ assert(Bitcode.getName() == "llvm.embedded.module");
+
+ ArrayType *AT = cast<ArrayType>(Bitcode.getValueType());
+ if (AT->getNumElements() != 0)
+ return false;
+
+ ArrayType *AT1 = ArrayType::get(AT->getElementType(), 1);
+ Constant *OneEltInit = Constant::getNullValue(AT1);
+ Bitcode.replaceInitializer(OneEltInit);
+ return true;
+}
+
+bool SPIRVPrepareGlobals::runOnModule(Module &M) {
+ const bool IsAMD = M.getTargetTriple().getVendor() == Triple::AMD;
+ if (!IsAMD)
+ return false;
+
+ bool Changed = false;
+ if (GlobalVariable *Bitcode = M.getNamedGlobal("llvm.embedded.module"))
+ Changed |= tryExtendLLVMBitcodeMarker(*Bitcode);
+
+ return Changed;
+}
+char SPIRVPrepareGlobals::ID = 0;
+
+} // namespace
+
+INITIALIZE_PASS(SPIRVPrepareGlobals, "prepare-globals",
+ "SPIRV prepare global variables", false, false)
+
+namespace llvm {
+ModulePass *createSPIRVPrepareGlobalsPass() {
+ return new SPIRVPrepareGlobals();
+}
+} // namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
index 2951a4bc695e2..10bbca225b20a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
@@ -59,6 +59,7 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTarget() {
initializeSPIRVEmitIntrinsicsPass(PR);
initializeSPIRVEmitNonSemanticDIPass(PR);
initializeSPIRVPrepareFunctionsPass(PR);
+ initializeSPIRVPrepareGlobalsPass(PR);
initializeSPIRVStripConvergentIntrinsicsPass(PR);
}
@@ -172,6 +173,7 @@ void SPIRVPassConfig::addIRPasses() {
addPass(createSPIRVRegularizerPass());
addPass(createSPIRVPrepareFunctionsPass(TM));
+ addPass(createSPIRVPrepareGlobalsPass());
}
void SPIRVPassConfig::addISelPrepare() {
diff --git a/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
new file mode 100644
index 0000000000000..72caa68b52930
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll
@@ -0,0 +1,24 @@
+; Expanding the bitcode marker works only for AMD at the moment
+; RUN: not llc -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o -
+; RUN: llc -verify-machineinstrs -mtriple=spirv64-amd-amdhsa %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -mtriple=spirv64-amd-amdhsa %s -o - -filetype=obj | spirv-val %}
+;
+; Verify that we lower the embedded bitcode
+
+@llvm.embedded.module = private addrspace(1) constant [0 x i8] zeroinitializer, section ".llvmbc", align 1
+@llvm.compiler.used = appending addrspace(1) global [1 x ptr addrspace(4)] [ptr addrspace(4) addrspacecast (ptr addrspace(1) @llvm.embedded.module to ptr addrspace(4))], section "llvm.metadata"
+
+; CHECK: OpName %[[#LLVM_EMBEDDED_MODULE:]] "llvm.embedded.module"
+; CHECK: OpDecorate %[[#LLVM_EMBEDDED_MODULE]] Constant
+; CHECK: %[[#UCHAR:]] = OpTypeInt 8 0
+; CHECK: %[[#UINT:]] = OpTypeInt 32 0
+; CHECK: %[[#ONE:]] = OpConstant %[[#UINT]] 1
+; CHECK: %[[#UCHAR_ARR_1:]] = OpTypeArray %[[#UCHAR]] %[[#ONE]]
+; CHECK: %[[#UCHAR_ARR_1_PTR:]] = OpTypePointer CrossWorkgroup %[[#UCHAR_ARR_1]]
+; CHECK: %[[#CONST_UCHAR_ARR_1:]] = OpConstantNull %[[#UCHAR_ARR_1]]
+; CHECK: %[[#LLVM_EMBEDDED_MODULE]] = OpVariable %[[#UCHAR_ARR_1_PTR]] CrossWorkgroup %[[#CONST_UCHAR_ARR_1]]
+
+define spir_kernel void @foo() {
+entry:
+ ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/fembed-bitcode.ll b/llvm/test/CodeGen/SPIRV/fembed-bitcode.ll
new file mode 100644
index 0000000000000..1e7106e0674c5
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/fembed-bitcode.ll
@@ -0,0 +1,32 @@
+; RUN: llc -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+; RUN: llc -verify-machineinstrs -mtriple=spirv64-amd-amdhsa %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -mtriple=spirv64-amd-amdhsa %s -o - -filetype=obj | spirv-val %}
+;
+; Verify that we can lower the embeded module and cmdline
+
+@llvm.embedded.module = private addrspace(1) constant [4 x i8] c"BC\C0\DE", section ".llvmbc", align 1
+@llvm.cmdline = private addrspace(1) constant [5 x i8] c"-cc1\00", section ".llvmcmd", align 1
+@llvm.compiler.used = appending addrspace(1) global [2 x ptr addrspace(4)] [ptr addrspace(4) addrspacecast (ptr addrspace(1) @llvm.embedded.module to ptr addrspace(4)), ptr addrspace(4) addrspacecast (ptr addrspace(1) @llvm.cmdline to ptr addrspace(4))], section "llvm.metadata"
+
+; CHECK: OpName %[[#LLVM_EMBEDDED_MODULE:]] "llvm.embedded.module"
+; CHECK: OpName %[[#LLVM_CMDLINE:]] "llvm.cmdline"
+; CHECK: OpDecorate %[[#LLVM_EMBEDDED_MODULE]] Constant
+; CHECK: OpDecorate %[[#LLVM_CMDLINE]] Constant
+; CHECK: %[[#UCHAR:]] = OpTypeInt 8 0
+; CHECK: %[[#UINT:]] = OpTypeInt 32 0
+; CHECK: %[[#FIVE:]] = OpConstant %[[#UINT]] 5
+; CHECK: %[[#UCHAR_ARR_5:]] = OpTypeArray %[[#UCHAR]] %[[#FIVE]]
+; CHECK: %[[#FOUR:]] = OpConstant %[[#UINT]] 4
+; CHECK: %[[#UCHAR_ARR_4:]] = OpTypeArray %[[#UCHAR]] %[[#FOUR]]
+; CHECK: %[[#UCHAR_ARR_5_PTR:]] = OpTypePointer CrossWorkgroup %[[#UCHAR_ARR_5]]
+; CHECK: %[[#UCHAR_ARR_4_PTR:]] = OpTypePointer CrossWorkgroup %[[#UCHAR_ARR_4]]
+; CHECK: %[[#CONST_UCHAR_ARR_4:]] = OpConstantComposite %[[#UCHAR_ARR_4]]
+; CHECK: %[[#LLVM_EMBEDDED_MODULE]] = OpVariable %[[#UCHAR_ARR_4_PTR]] CrossWorkgroup %[[#CONST_UCHAR_ARR_4]]
+; CHECK: %[[#CONST_UCHAR_ARR_5:]] = OpConstantComposite %[[#UCHAR_ARR_5]]
+; CHECK: %[[#LLVM_CMDLINE]] = OpVariable %[[#UCHAR_ARR_5_PTR]] CrossWorkgroup %[[#CONST_UCHAR_ARR_5]]
+
+define spir_kernel void @foo() {
+entry:
+ ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/llc-pipeline.ll b/llvm/test/CodeGen/SPIRV/llc-pipeline.ll
index 3fff2a8a24a73..6db375445e4a3 100644
--- a/llvm/test/CodeGen/SPIRV/llc-pipeline.ll
+++ b/llvm/test/CodeGen/SPIRV/llc-pipeline.ll
@@ -31,6 +31,7 @@
; SPIRV-O0-NEXT: Expand reduction intrinsics
; SPIRV-O0-NEXT: SPIR-V Regularizer
; SPIRV-O0-NEXT: SPIRV prepare functions
+; SPIRV-O0-NEXT: SPIRV prepare global variables
; SPIRV-O0-NEXT: FunctionPass Manager
; SPIRV-O0-NEXT: Lower invoke and unwind, for unwindless code generators
; SPIRV-O0-NEXT: Remove unreachable blocks from the CFG
@@ -130,6 +131,7 @@
; SPIRV-Opt-NEXT: Expand reduction intrinsics
; SPIRV-Opt-NEXT: SPIR-V Regularizer
; SPIRV-Opt-NEXT: SPIRV prepare functions
+; SPIRV-Opt-NEXT: SPIRV prepare global variables
; SPIRV-Opt-NEXT: FunctionPass Manager
; SPIRV-Opt-NEXT: Dominator Tree Construction
; SPIRV-Opt-NEXT: Natural Loop Information
|
a38d0d1 to
1e86b00
Compare
Add a pass where we can do IR->IR preprocessing of global-variables.
…ement array to a 1-element array When compiling with -fembed-bitcode-marker, Clang inserts a placeholder for the bitcode. This placeholder is a [0 x i8] array, which we cannot represent in SPIRV. For AMD flavoured SPIRV, we extend the llvm.embedded.module global to a zeroinitialized 1-element array.
dc89347 to
5815524
Compare
MrSidims
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe, there was a discussion about such issues in #149522 . While for me the patch is fine, I'd love to hear an opinion from @maarquitos14
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks reasonable to me. Just some food for thought about the name. I don't have any strong feelings about how the pass is named. Edit: I just saw the follow up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a problem with this. I think the problem with #149522 was that we were trying to make all 0-element array a 1-element array, while here it's only a specific array. I think this is safe.
Co-authored-by: Marcos Maronas <[email protected]>
Thanks ! Co-authored-by: Marcos Maronas <[email protected]>
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/123/builds/30517 Here is the relevant piece of the build log for the reference |
|
I looked at the reported buildbot failure and don't think it really is related to this patch. |
When compiling with
-fembed-bitcode-marker, Clang inserts a placeholderfor the bitcode. This placeholder is a
[0 x i8]array, which we cannotrepresent in SPIRV.
For AMD flavored SPIRV, we extend the
llvm.embedded.moduleglobal to azeroinitializer [1 x i8]array.To achieve this, this patch adds a new pass,
SPIRVPrepareGlobals, that we can use to write global variable's non-trivial-to-lower-IR -> trivial-to-lower-IR mappings.This is a second attempt at #162082, but cleaner.
In the translator something similar is done for every 0-element array since KhronosGroup/SPIRV-LLVM-Translator#2743 . But I don't think we want to do this mapping for all cases.